#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdio>
#include <map>
#include <time.h>
#include <algorithm>
#include <sstream>
#include <string.h>

#include "params.h"
#include "getopt.h" 
#include "model.h"
#include "genecan.h"

using namespace std;


int main(int argc, char* argv[])
{
	Params prm(argc, argv);

	// read model file, get all parameters
	ModelFile model = ModelFile();
	model.read(prm.model_fn);

	// read sequence file
	Sequence genome;
	genome.read(prm.seq_fn);

	// read lst file
	ifstream  file;
	file.open( prm.prediction_fn.c_str() );
	if ( !file.is_open() )
	{
		cout << "error on open file: " << prm.prediction_fn << endl;
		cin.get();
	}
	string line;
	bool SHARP = false;
	vector<GeneCandidate> genelist; // a gene list. points to the first gene;
	GeneCandidate *previous = NULL;// points to the left-side gene
	GeneCandidate *head = NULL;
	while( !file.eof() )
	{	
		getline( file, line );
		if(line.empty())
			continue;
		
		if(line.find_first_of('#') != string::npos){
			SHARP = true;
			continue;
		}
		if(SHARP){
			GeneCandidate  a_genecan(line);

			a_genecan.setGeneCan(genome.seq, model);
			//link this gene to the gene list
			if(genelist.size() == 0){
				genelist.push_back(a_genecan);
			}
			else{
				if(genelist[genelist.size() - 1].predicted_left < a_genecan.predicted_left){//assume input gene.lst is ordered
					genelist.push_back(a_genecan);
				}
				else{
					cout << "input gene.lst is not ordered" << endl;
					cin.get();
				}
			}

			//cout << line <<endl;
			//cout << a_gene.gene_seq.substr(0,3) << endl;
		}
	}
	cout << "all gene initiated"<<endl;
	cout << "gene" <<genelist.size() <<":\n";
	for( int i = 0; i < genelist.size() ; ++i){
		if(i == 0){
			genelist[i].prev = NULL;
			if(genelist.size() > 1)
				genelist[i].next = &genelist[i + 1];
			else
				genelist[i].next = NULL;
		}
		else if(i == genelist.size() - 1 ){
			genelist[i].prev = &genelist[i - 1];
			genelist[i].next = NULL;
		}
		else{
			genelist[i].prev = &genelist[i - 1];
			genelist[i].next = &genelist[i + 1];
		}
		genelist[i].calCod(model);
	//	genelist[i].calLocalCod(model);
	}
	for( int i = 0; i < genelist.size() ; ++i){
	//	cout << "gene" <<i <<":\n";
			genelist[i].calNoncoding(model);
	//	genelist[i].calLocalNoncoding(model);
	//	cout << "noncoding finished\n";
			genelist[i].calMotif(model);
	//	cout << "motif finished\n";
		//	genelist[i].calCod(model);
	//	cout << "cod finished\n";
			genelist[i].calForward(model);
	//	cout << "forward motif finished\n";
			genelist[i].calStartCodon(model);
		//cout << "start codon finished\n";
//			genelist[i].calStartPattern(model);
		//cout << "start pattern finished\n";
//			genelist[i].calCodPotential(model);

			genelist[i].calLength(model);

			/*if(genelist[i].strand == '+'){
				if( i == 0){
					genelist[i].calLength(model,1);
				}
				else{
					genelist[i].calLength(model,genelist[i-1].predicted_right);
				}
			}
			else{
				if( i == genelist.size() - 1){
					genelist[i].calLength(model, genome.seq.size() - 1);
				}
				else{
					genelist[i].calLength(model,genelist[i+1].predicted_left);
				}
			}*/
			Start max = genelist[i].getMaxStart();
			Start original = genelist[i].getOriginal();
			if(genelist[i].strand == '+'){
			//	cout << "+ "<< max.pos<< " " << genelist[i].geneCan_right << endl;
				//**
				cout << "+ "<< max.pos<< " " << genelist[i].geneCan_right << " " << max.score << " " << max.avgcod << " "<< max.avgnon << " " << max.motif <<" "<< max.nonLength <<" "<< max.startCodon <<  " * ";
				cout << "+ "<< original.pos<< " " << genelist[i].geneCan_right << " " << original.score << " " << original.avgcod << " "<< original.avgnon << " " << original.motif << " " << original.nonLength<<" "<< original.startCodon <<  endl;
				//**

				//**local approch, print only coding scores for all starts and real starts
		//		cout << "real: " << original.codP; 
		//		cout <<" + "<< original.pos<< " " << genelist[i].geneCan_right << " ";
		//		for(int k = genelist[i].starts.size() - 1; k >= 0; -- k  ){
		//			cout << genelist[i].starts[k].codP << " ";
		//		}
		//		cout << endl;
				//**
				
			}
			else if(genelist[i].strand == '-'){
				cout << "- " << genelist[i].geneCan_left << " "<< max.pos<<" " << max.score << " " << max.avgcod << " "<< max.avgnon << " " << max.motif <<" "<< max.nonLength << " "<< max.startCodon<<" * ";
				cout << "- "<<  genelist[i].geneCan_left <<" " << original.pos<<  " " << original.score << " " << original.avgcod << " "<< original.avgnon << " " << original.motif << " "<<original.nonLength<<" " << original.startCodon<< endl;
				//**local approch, print only coding scores for all starts and real starts
		//		cout << "real: " << original.codP;
		//		cout << " - "<<  genelist[i].geneCan_left <<" " << original.pos<<  " ";
		//		for(int k = genelist[i].starts.size() - 1; k >= 0; -- k  ){
		//			cout << genelist[i].starts[k].codP << " ";
		//		}
		//		cout << endl;
				
				//**
			}
	}

	cin.get();
}